﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Assist;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using YArchitech.Controls;
using YArchitech.Revit;
using YJKArch.Utils;
using HYOpeningCommon.DataEnum;
using HYOpeningCommon.Opening2D;
using HYOpeningCommon.OpeningDim;
using HYOpeningCommon.OpeningEX;
using HYOpeningCommon.ProvideData2TrackDim;
using HYOpeningCommon.Public;
using HYOpeningCreate.ConfigForm;
using HYView;
using TrackDim;

namespace HYOpeningCreate.Cmd
{
	[Transaction(TransactionMode.Manual)]
	[Regeneration(RegenerationOption.Manual)]
	internal class CmdOpeningDimension : IExternalCommand
	{
		[DllImport("user32.dll", EntryPoint = "SendMessageA")]
		public static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);

		public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
		{
			this.m_uiDoc = commandData.Application.ActiveUIDocument;
			this.m_doc = this.m_uiDoc.Document;
			CmdViewType types = (CmdViewType)11;
			if (SwitchView.SetUsableView(types, commandData) != Autodesk.Revit.UI.Result.Succeeded)
			{
				return Autodesk.Revit.UI.Result.Failed;
			}
			OpeningSignForm openingSignForm = new OpeningSignForm(this.m_uiDoc);
			if (openingSignForm.ShowDialog() == DialogResult.Cancel)
			{
				openingSignForm.Dispose();
				return Autodesk.Revit.UI.Result.Succeeded;
			}
			WindowHandle windowHandle = new WindowHandle(Process.GetCurrentProcess().MainWindowHandle);
			OpeningSignMainForm openingSignMainForm = new OpeningSignMainForm(windowHandle, this.m_uiDoc, ref CmdOpeningDimension.m_lstOpening);
			openingSignMainForm.Show(windowHandle);
			int wMsg = 7;
			CmdOpeningDimension.SendMessage(windowHandle.Handle, wMsg, IntPtr.Zero, IntPtr.Zero);
			double levelHeight = this.GetLevelHeight();
			CreateOpening2D createOpening2D = new CreateOpening2D(this.m_doc);
			this.m_lineStyleOpening2D = createOpening2D.GetOpening2DLineStyle();
			this.m_linePattern = createOpening2D.GetOpening2DLineStylePattern();
			this.m_filledRegionType = createOpening2D.GetOpening2DFilledRegionType();
			if (this.m_lineStyleOpening2D == null || this.m_linePattern == null || this.m_filledRegionType == null)
			{
				return Autodesk.Revit.UI.Result.Succeeded;
			}
			Selection selection = this.m_uiDoc.Selection;
			ISelectionFilter selectionFilter = new MassSelectionFilter();
			OpeningDim openingDim = new OpeningDim(this.m_doc);
			OpeningXData openingXData = new OpeningXData();
			if (openingDim == null || openingXData == null)
			{
				return Autodesk.Revit.UI.Result.Succeeded;
			}
			using (TransactionGroup transactionGroup = new TransactionGroup(this.m_doc))
			{
				try
				{
					transactionGroup.Start();
					for (;;)
					{
						EDimItemType rectOpeningDimType = EDimItemType.eUnknown;
						EDimItemType circleOpeningDimType = EDimItemType.eUnknown;
						try
						{
							List<FamilyInstance> list = selection.PickElementsByRectangle(selectionFilter, "请选择洞口").Cast<FamilyInstance>().ToList<FamilyInstance>();
							foreach (FamilyInstance familyInstance in list)
							{
								foreach (Element element in CmdOpeningDimension.m_lstOpening.Keys)
								{
									if (familyInstance.UniqueId == element.UniqueId && CmdOpeningDimension.m_lstOpening[element])
									{
										this.CreateOpening2D(familyInstance, openingXData, levelHeight);
									}
								}
							}
							XYZ vectorDim = new XYZ(1.0, 1.0, 0.0);
							if (openingSignMainForm.IsRadExtractDimensionChecked())
							{
								this.DimOperate(list, levelHeight, openingXData, openingDim, openingSignMainForm, ref vectorDim);
							}
							else
							{
								openingSignMainForm.GetDimSelected(ref rectOpeningDimType, ref circleOpeningDimType);
								string dimPrefix = openingSignMainForm.GetDimPrefix();
								if (dimPrefix == "")
								{
									YJKMessageBox.Show("标注前缀不可为空");
									continue;
								}
								List<Element> lstOpening = list.Cast<Element>().ToList<Element>();
								if (!openingDim.DimOpeningTable(commandData, lstOpening, dimPrefix, circleOpeningDimType, rectOpeningDimType))
								{
									continue;
								}
							}
							this.CreateTrackDim(list, openingXData, openingDim, vectorDim, levelHeight);
							List<Element> selElements = new List<Element>();
							RevitVersionFuncs.SetSelection(this.m_uiDoc.Selection, selElements);
							this.m_uiDoc.RefreshActiveView();
							continue;
						}
						catch (Exception)
						{
						}
						break;
					}
					openingSignMainForm.Close();
				}
				catch (Exception ex)
				{
					transactionGroup.RollBack();
					ExceptionLog.WriteLog(ex.Message, true);
					throw;
				}
				finally
				{
					ExceptionLog.CloseLogFile();
					transactionGroup.Assimilate();
				}
			}
			return Autodesk.Revit.UI.Result.Succeeded;
		}

		private void CreateTrackDim(List<FamilyInstance> lstFi, OpeningXData openingXData, OpeningDim openingDim, XYZ vectorDim, double dLevel)
		{
			foreach (FamilyInstance familyInstance in lstFi)
			{
				if (openingXData.ReadOpeningXData(familyInstance))
				{
					XYZ position = openingXData.m_position;
					int eOpeningProfile = openingXData.m_eOpeningProfile;
					string strDimUniqueId = openingXData.m_strDimUniqueId;
					XYZ xyz = openingXData.m_directionProfile.Normalize();
					string strHostUniqueId = openingXData.m_strHostUniqueId;
					double dAngle = openingXData.m_dAngle;
					bool flag = false;
					double dWidth = openingXData.m_dWidth;
					double dHeight = openingXData.m_dHeight;
					List<string> lstLineGuid = openingXData.m_lstLineGuid;
					if (openingXData.IsContainOpeningObj(familyInstance, ref flag))
					{
						Element element = this.m_doc.GetElement(strHostUniqueId);
						if (element != null)
						{
							TrackDimData trackDimData = new TrackDimData(this.m_doc);
							if (trackDimData.DeleteDimLine(lstLineGuid))
							{
								XYZ xyz2 = XYZ.Zero;
								XYZ xyz3 = new XYZ(position.X, position.Y, dLevel);
								XYZ xyz4 = null;
								BoundingBoxXYZ boundingBoxXYZ = element.get_BoundingBox(this.m_doc.ActiveView);
								ReferenceArray referenceArray = new ReferenceArray();
								XYZ xyz5 = XYZ.Zero;
								List<string> lstLineGuid2 = new List<string>();
								List<XYZ> list = new List<XYZ>();
								List<DimData> list2 = new List<DimData>();
								if (element is Floor)
								{
									if (eOpeningProfile == 0)
									{
										xyz2 = XYZ.BasisX;
										if (!this.GetRecentPt(boundingBoxXYZ, xyz2, xyz3, ref xyz4, strHostUniqueId, false) || xyz4 == null)
										{
											continue;
										}
										xyz4 = new XYZ(xyz4.X, xyz4.Y, xyz3.Z);
										xyz5 = (xyz4 - xyz3).Normalize();
										XYZ xyz6 = this.GetDimLineVec(vectorDim, xyz5);
										if (xyz6 == null)
										{
											continue;
										}
										Line line = trackDimData.CreateDimLine(xyz5, xyz6, xyz4, xyz3, 0.0);
										list.Add(xyz4);
										list.Add(xyz3);
										referenceArray = trackDimData.GetReference(ref lstLineGuid2, list, xyz6);
										if (referenceArray == null || referenceArray.IsEmpty)
										{
											continue;
										}
										DimData item = new DimData(line, referenceArray);
										list2.Add(item);
									}
									else
									{
										xyz2 = XYZ.BasisX;
										xyz2 = Transform.CreateRotation(XYZ.BasisZ, dAngle).OfVector(xyz2);
										if (!this.GetRecentPt(boundingBoxXYZ, xyz2, xyz3, ref xyz4, strHostUniqueId, true) || xyz4 == null)
										{
											continue;
										}
										xyz4 = new XYZ(xyz4.X, xyz4.Y, xyz3.Z);
										xyz5 = (xyz4 - xyz3).Normalize();
										XYZ xyz6 = this.GetDimLineVec(vectorDim, xyz5);
										if (xyz6 == null)
										{
											continue;
										}
										Line line = trackDimData.CreateDimLine(xyz5, xyz6, xyz4, xyz3, dWidth / 2.0);
										list.Add(xyz4);
										list.Add(xyz3 + xyz5.Negate() * dWidth / 2.0);
										list.Add(xyz3 + xyz5 * dWidth / 2.0);
										referenceArray = trackDimData.GetReference(ref lstLineGuid2, list, xyz6);
										if (referenceArray == null || referenceArray.IsEmpty)
										{
											continue;
										}
										DimData item2 = new DimData(line, referenceArray);
										list2.Add(item2);
										xyz2 = XYZ.BasisZ.CrossProduct(xyz2);
										if (!this.GetRecentPt(boundingBoxXYZ, xyz2, xyz3, ref xyz4, strHostUniqueId, true) || xyz4 == null)
										{
											continue;
										}
										xyz5 = (xyz4 - xyz3).Normalize();
										xyz6 = this.GetDimLineVec(vectorDim, xyz5);
										if (xyz6 == null)
										{
											continue;
										}
										line = trackDimData.CreateDimLine(xyz5, xyz6, xyz4, xyz3, dHeight / 2.0);
										list.Clear();
										list.Add(xyz4);
										list.Add(xyz3 + xyz5.Negate() * dHeight / 2.0);
										list.Add(xyz3 + xyz5 * dHeight / 2.0);
										referenceArray = trackDimData.GetReference(ref lstLineGuid2, list, xyz6);
										if (referenceArray == null || referenceArray.IsEmpty)
										{
											continue;
										}
										item2 = new DimData(line, referenceArray);
										list2.Add(item2);
									}
								}
								else if (element is Wall)
								{
									XYZ xyz6;
									if (xyz.AngleTo(vectorDim) < Math.PI*.5)
									{
										xyz6 = xyz.Negate().Normalize();
									}
									else
									{
										xyz6 = xyz.Normalize();
									}
									xyz2 = XYZ.BasisZ.CrossProduct(xyz).Normalize();
									if (!this.GetRecentPt(boundingBoxXYZ, xyz2, xyz3, ref xyz4, strHostUniqueId, true) || xyz4 == null)
									{
										continue;
									}
									xyz4 = new XYZ(xyz4.X, xyz4.Y, xyz3.Z);
									xyz5 = (xyz4 - xyz3).Normalize();
									Line line;
									if (eOpeningProfile == 0)
									{
										line = trackDimData.CreateDimLine(xyz5, xyz6, xyz4, xyz3, 0.0);
										list.Add(xyz4);
										list.Add(xyz3);
									}
									else
									{
										line = trackDimData.CreateDimLine(xyz5, xyz6, xyz4, xyz3, dWidth / 2.0);
										list.Add(xyz4);
										list.Add(xyz3 + xyz5.Negate() * dWidth / 2.0);
										list.Add(xyz3 + xyz5 * dWidth / 2.0);
									}
									referenceArray = trackDimData.GetReference(ref lstLineGuid2, list, xyz6);
									if (referenceArray == null || referenceArray.IsEmpty)
									{
										continue;
									}
									DimData item3 = new DimData(line, referenceArray);
									list2.Add(item3);
								}
								trackDimData.CreateDim(list2);
								Transaction transaction = new Transaction(this.m_doc, "SetLineUniqueId");
								try
								{
									transaction.Start();
									openingXData.SetLineUniqueId(lstLineGuid2, familyInstance);
									transaction.Commit();
								}
								catch (Exception)
								{
									transaction.RollBack();
								}
							}
						}
					}
				}
			}
		}

		private XYZ GetDimLineVec(XYZ vecDim, XYZ vecPosition2RecPt)
		{
			if (vecDim == null || vecPosition2RecPt == null)
			{
				return null;
			}
			XYZ xyz = XYZ.BasisZ.CrossProduct(vecPosition2RecPt).Normalize();
			if (Geometry.LessThan(xyz.AngleTo(vecDim), Math.PI*.5))
			{
				xyz = xyz.Negate().Normalize();
			}
			return xyz;
		}

		private bool GetRecentPt(BoundingBoxXYZ boundingBoxXYZ, XYZ vector, XYZ ptPosition, ref XYZ ptRecent, string strHostGUID, bool isHavingVector)
		{
			XYZ min = boundingBoxXYZ.Min;
			XYZ max = boundingBoxXYZ.Max;
			XYZ ptStart = ptPosition + vector * 100.0;
			XYZ ptEnd = ptPosition + vector.Negate() * 100.0;
			List<BuiltInCategory> list = new List<BuiltInCategory>();
            list.Add((BuiltInCategory)(-2000011));
            list.Add((BuiltInCategory)(-2000100));
			TrackDimensions trackDimensions = new TrackDimensions(this.m_doc, ptPosition, ptStart, ptEnd, strHostGUID, isHavingVector);
			ptRecent = trackDimensions.GetRecentPt(min, max, 0.0, list);
			return ptRecent != null;
		}

		private void DimOperate(List<FamilyInstance> lstFi, double dLevel, OpeningXData openingXData, OpeningDim openingDim, OpeningSignMainForm openingSignMainForm, ref XYZ vectorDim)
		{
			bool flag = false;
			if (lstFi.Count == 1)
			{
				flag = true;
			}
			XYZ xyz = null;
			XYZ xyz2 = null;
			foreach (FamilyInstance familyInstance in lstFi)
			{
				if (openingXData.ReadOpeningXData(familyInstance))
				{
					xyz = openingXData.m_position;
					int eOpeningProfile = openingXData.m_eOpeningProfile;
					string strDimUniqueId = openingXData.m_strDimUniqueId;
					bool isContainCircle = false;
					if (openingXData.IsContainOpeningObj(familyInstance, ref isContainCircle))
					{
						openingDim.DeleteOpeningDim(ref strDimUniqueId);
						if (this.SetDim(familyInstance, openingSignMainForm, eOpeningProfile))
						{
							if (!openingSignMainForm.IsChkDimensionPro())
							{
								isContainCircle = false;
							}
							if (flag)
							{
								xyz2 = this.m_uiDoc.Selection.PickPoint("选择另一点作引出标注");
							}
							else
							{
								xyz2 = xyz + new XYZ(4.0, 4.0, 0.0);
							}
							IndependentTag independentTag = openingDim.CreateDim(xyz, xyz2, isContainCircle, familyInstance);
							if (independentTag != null)
							{
								Transaction transaction = new Transaction(this.m_doc, "SetDimUniqueId");
								try
								{
									transaction.Start();
									openingXData.SetDimUniqueId(independentTag.UniqueId, familyInstance);
									transaction.Commit();
								}
								catch (Exception)
								{
									transaction.RollBack();
								}
							}
						}
					}
				}
			}
			if (flag && xyz != null && xyz2 != null)
			{
				XYZ xyz3 = new XYZ(xyz.X, xyz.Y, dLevel);
				vectorDim = (xyz2 - xyz3).Normalize();
				return;
			}
			vectorDim = new XYZ(1.0, 1.0, 0.0);
		}

		private bool SetDim(FamilyInstance fi, OpeningSignMainForm openingSignMainForm, int openingProfile)
		{
			EDimItemType edimItemType = EDimItemType.eUnknown;
			EDimItemType edimItemType2 = EDimItemType.eUnknown;
			openingSignMainForm.GetDimSelected(ref edimItemType, ref edimItemType2);
			if (edimItemType == EDimItemType.eUnknown || edimItemType2 == EDimItemType.eUnknown)
			{
				return false;
			}
			EDimItemType dimType;
			if (openingProfile == 0)
			{
				dimType = edimItemType2;
			}
			else
			{
				dimType = edimItemType;
			}
			new OpeningDim(this.m_doc).SetOpeningDim(dimType, fi);
			return true;
		}

		private void CreateOpening2D(Element elem, OpeningXData openingXData, double dValue)
		{
			openingXData.ReadOpeningXData(elem);
			if (openingXData.m_str2DUniqueId != "")
			{
				return;
			}
			XYZ xyz = openingXData.m_position;
			XYZ directionProfile = openingXData.m_directionProfile;
			double dWidth = openingXData.m_dWidth;
			XYZ xyz2 = XYZ.BasisZ.CrossProduct(directionProfile);
			double dHostWidth = openingXData.m_dHostWidth;
			double dPenetrationThickness = openingXData.m_dPenetrationThickness;
			double num;
			if (Geometry.IsEqual(dPenetrationThickness, 0.0))
			{
				num = dHostWidth;
			}
			else
			{
				xyz += directionProfile.Normalize() * (dHostWidth / 2.0 - dPenetrationThickness / 2.0);
				num = dPenetrationThickness;
			}
			XYZ xyz3 = new XYZ(xyz.X, xyz.Y, dValue);
			XYZ xyz4 = xyz3 + xyz2.Negate().Normalize() * dWidth / 2.0 + directionProfile.Normalize() * num / 2.0;
			XYZ xyz5 = xyz3 + xyz2.Negate().Normalize() * dWidth / 2.0 + directionProfile.Negate().Normalize() * num / 2.0;
			XYZ xyz6 = xyz3 * 2.0 - xyz4;
			XYZ xyz7 = xyz3 * 2.0 - xyz5;
			List<CurveLoop> list = new List<CurveLoop>();
			CurveLoop curveLoop = new CurveLoop();
			curveLoop.Append(Line.CreateBound(xyz4, xyz5));
			curveLoop.Append(Line.CreateBound(xyz5, xyz6));
			curveLoop.Append(Line.CreateBound(xyz6, xyz7));
			curveLoop.Append(Line.CreateBound(xyz7, xyz4));
			list.Add(curveLoop);
			Transaction transaction = new Transaction(this.m_doc, "CreateFilledRegion");
			try
			{
				transaction.Start();
				ViewPlan viewPlan = this.m_doc.ActiveView as ViewPlan;
				if (viewPlan == null)
				{
					transaction.RollBack();
				}
				else
				{
					FilledRegion filledRegion = FilledRegion.Create(this.m_doc, this.m_filledRegionType.Id, viewPlan.Id, list);
					filledRegion.SetLineStyleId(this.m_lineStyleOpening2D.Id);
					viewPlan.SetYJKProjLinePatternOverrideByElement(new List<ElementId>
					{
						filledRegion.Id
					}, this.m_linePattern);
					openingXData.Set2DUniqueId(filledRegion.UniqueId, elem);
					transaction.Commit();
				}
			}
			catch (Exception)
			{
				transaction.RollBack();
			}
		}

		private double GetLevelHeight()
		{
			return this.m_doc.ActiveView.GenLevel.Elevation;
		}

		public static Dictionary<Element, bool> GetOpenings()
		{
			return CmdOpeningDimension.m_lstOpening;
		}

		public static void SetOpenings(Dictionary<Element, bool> lstElem)
		{
			CmdOpeningDimension.m_lstOpening = lstElem;
		}

		private Document m_doc;

		private UIDocument m_uiDoc;

		private GraphicsStyle m_lineStyleOpening2D;

		private LinePatternElement m_linePattern;

		private FilledRegionType m_filledRegionType;

		private static Dictionary<Element, bool> m_lstOpening;
	}
}
